<template>
    <div class="shopping-cart-parabola">
        <div class="container" ref="containerRef">
            <div class="shopping-cart" ref="shoppingCartRef">
                <ShoppingCartOutlined style="font-size: 30px" />
            </div>
            <div class="add">
                <a-button type="primary" @click="handleClickAddToCart">加入购物车</a-button>
                <a-button type="primary" @click="handleClickAddToCart">加入购物车</a-button>
                <a-button type="primary" @click="handleClickAddToCart">加入购物车</a-button>
                <a-button type="primary" @click="handleClickAddToCart">加入购物车</a-button>
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { PlusCircleOutlined, ShoppingCartOutlined } from "@ant-design/icons-vue";
import { h, render } from "vue";
import { reactive } from "vue";
import { ref } from "vue";

const containerRef = ref<HTMLElement>();
const shoppingCartRef = ref<HTMLElement>();

const iconPosition = reactive({
    iconTop: "0px",
    iconLeft: "0px"
});

const move = reactive({
    x: "0px",
    y: "0px"
});

const handleClickAddToCart = (e: MouseEvent) => {
    const btn = e.target as HTMLElement;

    const { x, y, width } = btn.getBoundingClientRect();
    const cartPosition = shoppingCartRef.value!.getBoundingClientRect();

    // 1. 点击按钮创建元素
    const divEl = document.createElement("div");
    divEl.className = "add-cart-icon--wrapper";

    // 2. 渲染图标组件到divEl中
    const iconVNode = h("div", { class: "add-cart-icon" }, h(PlusCircleOutlined));
    render(iconVNode, divEl);

    // 3. 将 divEl 挂载到页面上
    containerRef.value!.append(divEl);

    // 4. 定位创建的元素初始位置为按钮上方
    iconPosition.iconTop = y - divEl.clientHeight + "px";
    iconPosition.iconLeft = x + width / 2 - divEl.clientWidth / 2 + "px";

    // 5. 计算移动距离
    move.x =
        cartPosition.x +
        cartPosition.width / 2 -
        divEl.clientWidth / 2 -
        (x + width / 2 - divEl.clientWidth / 2) +
        "px";

    move.y = cartPosition.y - y + divEl.clientHeight + "px";

    // 6. 动画结束移除元素
    divEl.addEventListener("animationend", () => {
        divEl.remove();
    });
};
</script>

<style scoped lang="scss">
/* 给父元素添加垂直方向移动动画 */
:global(.add-cart-icon--wrapper) {
    --top: v-bind(iconPosition.iconTop);
    --left: v-bind(iconPosition.iconLeft);
    --move-y: v-bind(move.y);

    position: fixed;
    top: var(--top);
    left: var(--left);
    border: 1px solid #3e3e3e;
    animation: move-y 0.5s cubic-bezier(0.43, -0.46, 0.88, 0.8) forwards;

    @keyframes move-y {
        to {
            transform: translateY(var(--move-y));
        }
    }
}

/* 给子元素添加水平移动动画 */
:global(.add-cart-icon) {
    --move-x: v-bind(move.x);

    display: flex;
    align-items: center;
    font-size: 20px;
    animation: move-x 0.5s linear forwards;

    @keyframes move-x {
        100% {
            transform: translateX(var(--move-x));
        }
    }
}
.shopping-cart-parabola {
    .container {
        position: relative;
        width: 375px;
        height: 700px;
        margin: 0 auto;
        border: 1px solid #3e3e3e;
        .shopping-cart {
            position: absolute;
            bottom: 20px;
            left: 10px;
        }
        .add {
            position: absolute;
            right: 10px;
            display: flex;
            flex-flow: column;
            justify-content: space-evenly;
            height: 100%;
        }
    }
}
</style>
